package com.bsoft.advance.server.processor;

import com.bsoft.advance.core.common.ServiceInfo;
import com.bsoft.advance.core.register.DiscoveryService;
import com.bsoft.advance.core.register.RegistryService;
import com.bsoft.advance.server.cache.RpcServiceCache;
import com.bsoft.advance.server.annotation.RpcService;
import com.bsoft.advance.server.config.RpcServerProperties;
import com.bsoft.advance.server.transport.NettyServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.CommandLineRunner;

import java.net.InetAddress;

@Slf4j
public class RpcServerProcessor implements BeanPostProcessor , CommandLineRunner {

    @Autowired
    NettyServer server;
    @Autowired
    RpcServerProperties properties;
    @Autowired
    RegistryService registryService;

    /**
     * bean实例化之后，对开放的bean进行缓存（遍历@RpcService注解）
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        RpcService rpcService = bean.getClass().getAnnotation(RpcService.class);
        if (rpcService != null) {
            try {
                // 放入缓存，以供调用
                RpcServiceCache.putService(rpcService.interfaceType().getName(), bean);
                // 注册到注册中心上
                ServiceInfo serviceInfo = new ServiceInfo();
                serviceInfo.setAppName(properties.getAppName());
                serviceInfo.setServiceName(rpcService.interfaceType().getName());
                serviceInfo.setAddress(InetAddress.getLocalHost().getHostAddress());
                serviceInfo.setPort(properties.getPort());
                registryService.register(serviceInfo);
                log.info("service[{}] is online", rpcService.interfaceType().getName());
            } catch (Exception e) {
                log.error("服务注册失败：", e);
            }
        }
        return bean;
    }

    @Override
    public void run(String... args) throws Exception {
        // 服务端启动
        new Thread(() -> {
            server.start(properties.getPort());
        }).start();

        // 通过添加一个jvm关闭钩子，实现服务下线后，把注册中心的服务节点清除掉，避免客户端再向该节点发起请求
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                registryService.destroy();
                log.info("all service is offline！");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }));
    }
}
